import type { GridColDef, GridRowModel } from '@mui/x-data-grid-pro';
import type {
  GridPivotingPrivateApiCommunity,
  GridPivotingStatePartial,
} from '@mui/x-data-grid/internals';
import type { RefObject } from '@mui/x-internals/types';
import type { DataGridPremiumProcessedProps } from '../../../models/dataGridPremiumProps';
import type { GridInitialStatePremium } from '../../../models/gridStatePremium';

export type GridPivotingStaticPropsOverrides = {
  rowGroupingModel: DataGridPremiumProcessedProps['rowGroupingModel'];
  getAggregationPosition: DataGridPremiumProcessedProps['getAggregationPosition'];
  columnVisibilityModel: DataGridPremiumProcessedProps['columnVisibilityModel'];
  groupingColDef: DataGridPremiumProcessedProps['groupingColDef'];
  headerFilters: DataGridPremiumProcessedProps['headerFilters'];
  disableAggregation: DataGridPremiumProcessedProps['disableAggregation'];
  disableRowGrouping: DataGridPremiumProcessedProps['disableRowGrouping'];
};

export type GridPivotingDynamicPropsOverrides = {
  rows?: DataGridPremiumProcessedProps['rows'];
  columns: DataGridPremiumProcessedProps['columns'];
  aggregationModel: DataGridPremiumProcessedProps['aggregationModel'];
  columnGroupingModel: DataGridPremiumProcessedProps['columnGroupingModel'];
};

export type GridPivotingPropsOverrides = GridPivotingStaticPropsOverrides &
  GridPivotingDynamicPropsOverrides;

export interface GridPivotingState extends GridPivotingStatePartial {
  model: GridPivotModel;
  propsOverrides: GridPivotingPropsOverrides | GridPivotingStaticPropsOverrides | {} | undefined;
}

export interface GridPivotingInitialState {
  model?: GridPivotModel;
  enabled?: boolean;
  /**
   * To open the pivot sidebar on init, set sidebar's `openValue` to `GridSidebarValue.Pivot`.
   * @deprecated Use sidebar state instead.
   */
  panelOpen?: boolean;
}

export interface GridPivotModel {
  columns: { field: GridColDef['field']; sort?: 'asc' | 'desc'; hidden?: boolean }[];
  rows: {
    field: GridColDef['field'];
    hidden?: boolean;
  }[];
  values: {
    field: GridColDef['field'];
    aggFunc: string;
    hidden?: boolean;
  }[];
}

export type DropPosition = 'top' | 'bottom' | null;

export interface GridPivotingApi {
  /**
   * Sets the pivot model to use in the pivot mode.
   * @param {GridPivotModel | ((prev: GridPivotModel) => GridPivotModel)} model - The pivot model to set.
   */
  setPivotModel: (model: GridPivotModel | ((prev: GridPivotModel) => GridPivotModel)) => void;
  /**
   * Sets whether the pivot mode is active.
   * @param {boolean | ((prev: boolean) => boolean)} active - The new value of the pivot mode state.
   */
  setPivotActive: (active: boolean | ((prev: boolean) => boolean)) => void;
  /**
   * Sets whether the pivot panel is open.
   * @deprecated Use the `showSidebar` method instead. Using this method will not trigger the `sidebarOpen` and `sidebarClose` events.
   * @param {boolean | ((prev: boolean) => boolean)} open - The new value of the pivot panel open state.
   */
  setPivotPanelOpen: (open: boolean | ((prev: boolean) => boolean)) => void;
}

export interface GridPivotingPrivateApi extends GridPivotingPrivateApiCommunity {
  updatePivotModel: (params: {
    field: string;
    targetSection: 'columns' | 'rows' | 'values' | null;
    originSection: 'columns' | 'rows' | 'values' | null;
    targetField?: string;
    targetFieldPosition?: DropPosition;
  }) => void;
}

export type GridPivotingColDefOverrides = Pick<
  GridColDef,
  | 'field'
  | 'width'
  | 'flex'
  | 'headerName'
  | 'description'
  | 'align'
  | 'headerAlign'
  | 'cellClassName'
  | 'headerClassName'
  | 'display'
  | 'maxWidth'
  | 'minWidth'
  | 'resizable'
  | 'sortingOrder'
>;

/**
 * The column definition overrides callback for the columns generated by the pivoting feature.
 * @param {string} originalColumnField The field of the original column.
 * @param {string[]} columnGroupPath The path of the column groups the column belongs to.
 * @returns {Partial<GridPivotingColDefOverrides> | undefined | void} The column definition overrides.
 */
export type PivotingColDefCallback = (
  originalColumnField: GridColDef['field'],
  columnGroupPath: string[],
) => Partial<GridPivotingColDefOverrides> | undefined;

export interface GridPivotingInternalCache {
  nonPivotDataRef: RefObject<
    | {
        rows: GridRowModel[];
        columns: Map<string, GridColDef>;
        originalRowsProp: readonly GridRowModel[];
      }
    | undefined
  >;
  exportedStateRef: RefObject<GridInitialStatePremium | null>;
}
